package org.chnxi.study.nio.netty.groupchat;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

public class NioGroupChatServer {

    private final int port;

    public NioGroupChatServer(int port){
        this.port = port;
    }

    NioEventLoopGroup bossGroup;

    NioEventLoopGroup workerGroup;

    ServerBootstrap bootstrap;

    public void run(){

        bossGroup = new NioEventLoopGroup(1);
        workerGroup = new NioEventLoopGroup();

        try{
         bootstrap = new ServerBootstrap();
         bootstrap.group(bossGroup , workerGroup)
                 .channel(NioServerSocketChannel.class)
                 .option(ChannelOption.SO_BACKLOG , 128)
                 .childOption(ChannelOption.SO_KEEPALIVE , true)
                 .childHandler(new ChannelInitializer<SocketChannel>() {
                     @Override
                     protected void initChannel(SocketChannel socketChannel) throws Exception {
                         socketChannel.pipeline().addLast("StringDecoder" , new StringDecoder());
                         socketChannel.pipeline().addLast("StringEncoder" , new StringEncoder());
                         socketChannel.pipeline().addLast("ChatHandler" , new NioGroupChatServerHandler());

                         //说明：
                         //IdleStateHandler 是netty提供的处理空闲状态的处理器
                         // readerIdleTime: 表示多长时间没有从通道中读取数据，就发送一个心跳检测报告，检测连接是否正常
                         // writerIdleTime: 表示多长时间没有从通道中写入数据，就发送一个心跳检测报告，检测连接是否正常
                         // allIdleTime: 表示多长时间没有发生过读写操作，就发送一个心跳检测报告，检测连接是否正常
                         // 当 IdleStateEvent触发后，就会传递给管道的下一个handler去处理，通过触发下一个handler的
                         // userEventTiggered，在该方法中处理IdleStateEvent
                         socketChannel.pipeline().addLast("IdleStateHandler" ,new IdleStateHandler(10 , 20 , 30 , TimeUnit.SECONDS));
                         // 加入一个堆空闲检测进一步处理的handler，需要自定义
                         socketChannel.pipeline().addLast(new NioGroupChatServerHeartbeatHandler());

                     }
                 });
         System.out.println("==========服务已启动==========");
         ChannelFuture future = bootstrap.bind(port).sync();
         future.channel().closeFuture().sync();

        }catch (Exception e){
            e.printStackTrace();
            System.exit(-1);
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        NioGroupChatServer server = new NioGroupChatServer(6666);
        server.run();
    }

}
